package com.cqhz.quwan.util;

import android.util.Log;

import com.cqhz.quwan.model.BallSelectedBean;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * 竞猜篮球奖金和串法工具类
 * Created by Guojing on 2018/12/19.
 * <p>
 * 0：主负
 * 1：主胜
 * 2：让分主负
 * 3：让分主胜
 * 4：大分
 * 5：小分
 * 6：1-5
 * 7：6-10
 * 8：11-15
 * 9：16-20
 * 10：21-25
 * 11：26+
 * 12：1-5
 * 13：6-10
 * 14：11-15
 * 15：16-20
 * 16：21-25
 * 17：26+
 */
public class BasketBallBetUtils
{
    // 选球投注号对应比赛结果 APP端
    public static       Map<Integer, String>          scoreMap     = new HashMap<>();
    // 比赛结果对应投注号 后端
    public static       Map<String, Integer>          ballMap      = new HashMap<>();
    // 胜负
    public static final Integer[]                     sfKey        = {0, 1};
    // 让分胜负
    public static final Integer[]                     rfsfKey      = {2, 3};
    // 大小分
    public static final Integer[]                     dxfKey       = {4, 5};
    // 胜分差
    public static final Integer[]                     sfcKey       = {6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
    // 串玩法
    public static final String[]                      bunchKey     = {
            "2-1", "3-1", "4-1", "5-1", "6-1", "7-1", "8-1",
            "3-3", "3-4",
            "4-4", "4-5", "4-6", "4-11",
            "5-5", "5-6", "5-10", "5-16", "5-20", "5-26",
            "6-6", "6-7", "6-15", "6-20", "6-22", "6-35", "6-42", "6-50", "6-57",
            "7-7", "7-8", "7-21", "7-35", "7-120",
            "8-8", "8-9", "8-28", "8-56", "8-70", "8-247", "8-255"
    };
    // 串列表
    public static       List<List<BallBunch>>         bunchList    = new ArrayList<>();
    // 串map
    public static       Map<Integer, List<BallBunch>> bunchMap     = new HashMap<>();
    // 过关投注对应选球
    public static       Map<String, Integer[]>        betMethodMap = new HashMap<>();
    private static      DecimalFormat                 df           = new DecimalFormat("#.00");

    static
    {
        initScoreMap();
        initBallMap();
        initBunchList();
        initBetMethodMap();
        bunchMap.put(1, new ArrayList<BallBunch>());
        bunchMap.put(2, new ArrayList<BallBunch>());
    }

    private static void initScoreMap()
    {
        // 胜负
        scoreMap.put(0, "主负");
        scoreMap.put(1, "主胜");
        // 让分胜负
        scoreMap.put(2, "主负");
        scoreMap.put(3, "主胜");
        // 大小分
        scoreMap.put(4, "大分");
        scoreMap.put(5, "小分");
        // 胜分差
        scoreMap.put(6, "主负（1-5）");
        scoreMap.put(7, "主负（6-10）");
        scoreMap.put(8, "主负（11-15）");
        scoreMap.put(9, "主负（16-20）");
        scoreMap.put(10, "主负（21-25）");
        scoreMap.put(11, "主负（26+）");
        scoreMap.put(12, "主胜（1-5）");
        scoreMap.put(13, "主胜（6-10）");
        scoreMap.put(14, "主胜（11-15）");
        scoreMap.put(15, "主胜（16-20）");
        scoreMap.put(16, "主胜（21-25）");
        scoreMap.put(17, "主胜（26+）");
    }

    private static void initBallMap()
    {
        // 胜负
        ballMap.put("主负", 0);
        ballMap.put("主胜", 1);
        // 让分胜负
        ballMap.put("让分主负", 2);
        ballMap.put("让分主胜", 3);
        // 大小分
        ballMap.put("大分", 4);
        ballMap.put("小分", 5);
        // 胜分差
        ballMap.put("主负（1-5）", 6);
        ballMap.put("主负（6-10）", 7);
        ballMap.put("主负（11-15）", 8);
        ballMap.put("主负（16-20）", 9);
        ballMap.put("主负（21-25）", 10);
        ballMap.put("主负（26+）", 11);
        ballMap.put("主胜（1-5）", 12);
        ballMap.put("主胜（6-10）", 13);
        ballMap.put("主胜（11-15）", 14);
        ballMap.put("主胜（16-20）", 15);
        ballMap.put("主胜（21-25）", 16);
        ballMap.put("主胜（26+）", 17);
    }

    /**
     * 说   明： 获取篮球串法限制
     * 作   者：	Guojing
     * 创建时间：	2018/12/19 16:50
     *
     * @param matchNum 场次个数
     * @param playType 1：胜负；2：让分胜负；3：胜分差；4：大小分；5：混合过关；6：单关；
     **/
    public static Map<Integer, List<BallBunch>> getBallBunch(int matchNum, int playType, Object[][] betList, boolean isdg)
    {
        bunchMap.get(1).clear();
        bunchMap.get(2).clear();
        // 胜分差最多4关
        if (matchNum > 4 && playType == 3)
        {
            matchNum = 4;
        }
        // 混合投注中包含了胜分差的，串关方式最多4关
        if (matchNum > 4 && playType == 5)
        {
            Set<Integer> set = new HashSet<>();
            for (Object[] bets : betList)
            {
                for (Object bet : bets)
                    set.add((Integer) bet);
            }
            List<Integer> list = new ArrayList(set);
            Collections.sort(list);
            Collections.reverse(list);
            for (Integer k : list)
            {
                if (k >= sfcKey[0])
                {
                    matchNum = matchNum > 4 ? 4 : matchNum;
                    break;
                }
                else
                {
                    break;
                }
            }
        }
        //最大支持8关
        if (matchNum > 8)
            matchNum = 8;
        //是否单关
        if (isdg)
        {
            bunchMap.get(1).add(new BallBunch("1-1", "单关", false));
        }
        bunchMap.get(1).addAll(bunchList.get(1).subList(0, matchNum - 1));
        for (int m = 3; m <= matchNum; m++)
        {
            bunchMap.get(2).addAll(bunchList.get(m));
        }
        return bunchMap;
    }

    private static void initBunchList()
    {
        for (int i = 0; i < 9; i++)
        {
            bunchList.add(new ArrayList<BallBunch>());
        }
        for (String bunch : bunchKey)
        {
            if (bunch.endsWith("-1"))
            {
                bunchList.get(1).add(new BallBunch(bunch, bunch.replace("-", "串"), false));
                continue;
            }
            if (bunch.startsWith("2-"))
            {
                bunchList.get(2).add(new BallBunch(bunch, bunch.replace("-", "串"), false));
            }
            if (bunch.startsWith("3-"))
            {
                bunchList.get(3).add(new BallBunch(bunch, bunch.replace("-", "串"), false));
            }
            if (bunch.startsWith("4-"))
            {
                bunchList.get(4).add(new BallBunch(bunch, bunch.replace("-", "串"), false));
            }
            if (bunch.startsWith("5-"))
            {
                bunchList.get(5).add(new BallBunch(bunch, bunch.replace("-", "串"), false));
            }
            if (bunch.startsWith("6-"))
            {
                bunchList.get(6).add(new BallBunch(bunch, bunch.replace("-", "串"), false));
            }
            if (bunch.startsWith("7-"))
            {
                bunchList.get(7).add(new BallBunch(bunch, bunch.replace("-", "串"), false));
            }
            if (bunch.startsWith("8-"))
            {
                bunchList.get(8).add(new BallBunch(bunch, bunch.replace("-", "串"), false));
            }
        }
    }

    private static void initBetMethodMap()
    {
        betMethodMap.put("1-1", new Integer[]{1});
        betMethodMap.put("2-1", new Integer[]{2});
        betMethodMap.put("2-3", new Integer[]{1, 2});
        betMethodMap.put("3-1", new Integer[]{3});
        betMethodMap.put("3-3", new Integer[]{2});
        betMethodMap.put("3-4", new Integer[]{2, 3});
        betMethodMap.put("3-6", new Integer[]{1, 2});
        betMethodMap.put("3-7", new Integer[]{1, 2, 3});
        betMethodMap.put("4-1", new Integer[]{4});
        betMethodMap.put("4-4", new Integer[]{3});
        betMethodMap.put("4-5", new Integer[]{3, 4});
        betMethodMap.put("4-6", new Integer[]{2});
        betMethodMap.put("4-10", new Integer[]{1, 2});
        betMethodMap.put("4-11", new Integer[]{2, 3, 4});
        betMethodMap.put("4-14", new Integer[]{1, 2, 3});
        betMethodMap.put("4-15", new Integer[]{1, 2, 3, 4});
        betMethodMap.put("5-1", new Integer[]{5});
        betMethodMap.put("5-5", new Integer[]{4});
        betMethodMap.put("5-6", new Integer[]{4, 5});
        betMethodMap.put("5-10", new Integer[]{2});
        betMethodMap.put("5-15", new Integer[]{1, 2});
        betMethodMap.put("5-16", new Integer[]{3, 4, 5});
        betMethodMap.put("5-20", new Integer[]{2, 3});
        betMethodMap.put("5-25", new Integer[]{1, 2, 3});
        betMethodMap.put("5-26", new Integer[]{2, 3, 4, 5});
        betMethodMap.put("5-30", new Integer[]{1, 2, 3, 4});
        betMethodMap.put("5-31", new Integer[]{1, 2, 3, 4, 5});
        betMethodMap.put("6-1", new Integer[]{6});
        betMethodMap.put("6-6", new Integer[]{5});
        betMethodMap.put("6-7", new Integer[]{5, 6});
        betMethodMap.put("6-15", new Integer[]{2});
        betMethodMap.put("6-20", new Integer[]{3});
        betMethodMap.put("6-21", new Integer[]{1, 2});
        betMethodMap.put("6-22", new Integer[]{4, 5, 6});
        betMethodMap.put("6-35", new Integer[]{2, 3});
        betMethodMap.put("6-41", new Integer[]{1, 2, 3});
        betMethodMap.put("6-42", new Integer[]{3, 4, 5, 6});
        betMethodMap.put("6-50", new Integer[]{2, 3, 4});
        betMethodMap.put("6-56", new Integer[]{1, 2, 3, 4});
        betMethodMap.put("6-57", new Integer[]{2, 3, 4, 5, 6});
        betMethodMap.put("6-62", new Integer[]{1, 2, 3, 4, 5});
        betMethodMap.put("6-63", new Integer[]{1, 2, 3, 4, 5, 6});
        betMethodMap.put("7-1", new Integer[]{7});
        betMethodMap.put("7-7", new Integer[]{6});
        betMethodMap.put("7-8", new Integer[]{6, 7});
        betMethodMap.put("7-21", new Integer[]{5});
        betMethodMap.put("7-35", new Integer[]{4});
        betMethodMap.put("7-120", new Integer[]{2, 3, 4, 5, 6, 7});
        betMethodMap.put("7-127", new Integer[]{1, 2, 3, 4, 5, 6, 7});
        betMethodMap.put("8-1", new Integer[]{8});
        betMethodMap.put("8-8", new Integer[]{7});
        betMethodMap.put("8-9", new Integer[]{7, 8});
        betMethodMap.put("8-28", new Integer[]{6});
        betMethodMap.put("8-56", new Integer[]{5});
        betMethodMap.put("8-70", new Integer[]{4});
        betMethodMap.put("8-247", new Integer[]{2, 3, 4, 5, 6, 7, 8});
        betMethodMap.put("8-255", new Integer[]{1, 2, 3, 4, 5, 6, 7, 8});
    }

    /**
     * 说    明：   计算投注注数
     *
     * @param betBunchs 选择的串玩法
     * @param list      投注场次和投注号码
     *                  创 建 人：	Guojing
     *                  创建时间：	2018/12/19
     *                  修 改 人：
     *                  修改日期：
     **/
    public static Integer betNum(String[] betBunchs, Object[][] list)
    {
        Combination cb = new Combination(list);
        int num = 0;
        for (String betBunch : betBunchs)
        {
            Integer[] bunch = betMethodMap.get(betBunch);
            if (null != bunch)
            {
                for (Integer m : bunch)
                {
                    List<Object[][]> cm = cb.select(m);
                    for (Object[][] arr : cm)
                    {
                        int _zNum = 1;
                        for (int i = 0; i < arr.length; i++)
                        {
                            _zNum *= arr[i].length;
                        }
                        num += _zNum;
                    }
                }
            }
        }
        return num;
    }

    /**
     * 说   明： 根据单场的投注号获取投注赔率的最小值和最大值
     * 作   者：	Guojing
     * 创建时间：	2018/12/19
     *
     * @param betNum  选中的串法值
     * @param oddsMap 选中场次的玩法map
     **/
    public static Double[] getMinMaxOdds(Integer[] betNum, Map<Integer, String> oddsMap)
    {
        Double min = Double.parseDouble(oddsMap.get(betNum[0]));
        Double max = 0.0;
        Map<Integer, Double> betMap = new HashMap<>();
        for (Integer num : betNum)
        {
            String s = oddsMap.get(num);
            if (null != s)
            {
                Double d = Double.parseDouble(s);
                if (min > d)
                    min = d;
                betMap.put(num, d);
            }
        }
        max += getMaxOdds(sfKey, betMap);
        max += getMaxOdds(rfsfKey, betMap);
        max += getMaxOdds(dxfKey, betMap);
        max += getMaxOdds(sfcKey, betMap);
        return new Double[]{min, max};
    }

    /**
     * 说    明：   根据玩法获取投注最大值
     * 创 建 人：    Guojing
     * 创建时间：    2018/12/19
     * 修 改 人：
     * 修改日期：
     **/
    public static Double getMaxOdds(Integer[] key, Map<Integer, Double> betMap)
    {
        Double _max = 0.0;
        for (Integer num : key)
        {
            Double d = betMap.get(num);
            if (null != d && d > _max)
            {
                _max = d;
            }
        }
        return _max;
    }

    /**
     * 说    明：    最小获奖值
     * 创 建 人：    Guojing
     * 创建时间：    2018/12/19
     * 修 改 人：
     * 修改日期：
     **/
    public static Double betMinVal(String[] betBunchs, List<Double[]> list)
    {
        List<Integer> numList = new ArrayList<>();
        for (String betBunch : betBunchs)
        {
            Integer[] bunch = betMethodMap.get(betBunch);
            if (null != bunch)
            {
                numList.addAll(Arrays.asList(bunch));
            }
        }
        if (numList.size() == 0)
            return 0.00;
        Collections.sort(numList);
//        numList.ss;
        //获取最小值列表并排序
        List<Double> minList = new ArrayList<>();
        for (Double[] d : list)
        {
            List<Double> _minList = new ArrayList<>();
            for (Double _d : d)
            {
                _minList.add(_d);
            }
            Collections.sort(_minList);
            minList.add(_minList.get(0));
        }
        Collections.sort(minList);
        Double val = 2.0;

        for (int i = 0; i < numList.get(0); i++)
        {
            val *= minList.get(i);
        }
        return val;
    }

    /**
     * 说    明：   最大获奖值
     * 创 建 人：    Guojing
     * 创建时间：    2018/12/19
     * 修 改 人：
     * 修改日期：
     **/
    public static Double betMaxVal(String[] betBunchs, List<Double[]> list)
    {
        Double max = 0.0;
        Double[] _max = new Double[list.size()];
        for (int i = 0; i < list.size(); i++)
        {
            _max[i] = list.get(i)[1];
        }
        Combination cb = new Combination(_max);
        for (String betBunch : betBunchs)
        {
            Integer[] bunch = betMethodMap.get(betBunch);
            if (null != bunch)
            {
                for (Integer m : bunch)
                {
                    List<Double[]> cm = cb.select(m);
                    for (Double[] arr : cm)
                    {
                        Double d = 2.0;
                        for (Double _d : arr)
                            d *= _d;
                        max += d;
                    }
                }
            }
        }
        return max;
    }

    /**
     * 说   明： 获取投注获胜的最小场次
     * 作   者：	Guojing
     * 创建时间：	2018/11/24 10:16
     *
     * @param betBunchs 选中的串法值
     * @return 最小场次
     */
    public static Integer bunchNum(String[] betBunchs)
    {
        Set<Integer> set = new HashSet<>();
        for (String betBunch : betBunchs)
        {
            Integer[] bunch = betMethodMap.get(betBunch);
            if (null != bunch)
            {
                for (Integer m : bunch)
                    set.add(m);
            }
        }
        List<Integer> list = new ArrayList<>();
        for (Integer i : set)
            list.add(i);
        return list.size() > 0 ? list.get(0) : 2;
    }


    /**
     * 说 明：            计算投注注数
     *
     * @param betBunches 选择的串玩法
     * @param list       投注场次和投注号码
     *                   创 建 人：	郭靖
     *                   修 改 人：	maradona1984
     *                   创建时间：	2018/12/25 10:55
     **/
    public static List<List<Object>> getBetList(String[] betBunches, Object[][] list)
    {
        Combination cb = new Combination(list);
        List<List<Object>> cmNew = new ArrayList<>();
        for (String betBunch : betBunches)
        {
            Integer num = Integer.valueOf(betBunch);
            List<Object[][]> cm = cb.select(num);
            for (int i = 0; i < cm.size(); i++)
            {
                Object[][] c = cm.get(i);
                List<Object> objectList = new ArrayList<>();
                combination(cmNew, objectList, c, 0);
            }
        }
        Log.e("getBetList()", cmNew.toArray().toString());
        return cmNew;
    }

    /**
     * 说 明：            递归组合
     *
     * @param cmNew
     * @param objectList
     * @param objectss
     * @param index      索引
     *                   创 建 人：	周颠
     *                   修 改 人：	郭靖
     *                   创建时间：	2018/12/25 10:55
     */
    public static void combination(List<List<Object>> cmNew, List<Object> objectList, Object[][] objectss, int index)
    {
        int nextIndex = index + 1;
        for (Object object : objectss[index])
        {
            List<Object> tempList = new ArrayList<>(objectList);
            tempList.add(object);
            if (objectss.length > nextIndex)
            {
                combination(cmNew, tempList, objectss, nextIndex);
            }
            else
            {
                cmNew.add(tempList);
            }
        }
    }
    /**
     * @return void
     * @Author 苦智
     * @Description 搏冷博热奖金优化
     * @Date 11:39 2018/12/27
     * @Param [dl, betAmt, type] 奖金优化投注列表、投注金额、（1博热 2搏冷）
     **/
    public static void hotOrColdOptimize(List<BallSelectedBean> dl, BigDecimal betAmt, Integer type)
    {
        sortByAttribute(dl, 1);
        if (type == 2)
        {
            sortByAttribute(dl, 2);
        }
        int bets = 0;
        for (BallSelectedBean item : dl)
        {
            BigDecimal basePrize = new BigDecimal(item.getSinglePrize());
            BigDecimal b = betAmt.divide(basePrize, BigDecimal.ROUND_UP);
            int betNum = b.intValue();
            bets += betNum;
            item.setBetNum(betNum + "");
            item.setTotalPrize(basePrize.multiply(new BigDecimal(betNum)).toString());
        }
        BallSelectedBean item = dl.get(0);
        int distributeBet = betAmt.divide(new BigDecimal(200)).intValue() - bets;
        int betNum = Integer.valueOf(item.getBetNum()) + distributeBet;
        BigDecimal basePrize = new BigDecimal(item.getSinglePrize());
        item.setBetNum(betNum + "");
        item.setTotalPrize(basePrize.multiply(new BigDecimal(betNum)).toString());
    }

    /**
     * @return void
     * @Author 苦智
     * @Description 奖金平均优化
     * @Date 14:58 2018/12/25
     * @Param [dl, betNums] dl：投注列表、需要分配的注数
     **/
    public static void prizeOptimize(List<BallSelectedBean> dl, Integer betNums)
    {
        while (betNums > 0)
        {
            sortByAttribute(dl, 1);
            int betNum = Integer.valueOf(dl.get(0).getBetNum()) + 1;
            dl.get(0).setTotalPrize(new BigDecimal(dl.get(0).getSinglePrize()).multiply(new BigDecimal(betNum)).toString());
            dl.get(0).setBetNum(betNum + "");
            betNums--;
        }
        sortByAttribute(dl, 0);
    }

    /**
     * 按照List中的某个对象属性值(Int、double、bigdecimal类型的属性)进行排序
     *
     * @param list、type(0：奖金排序 1：单倍奖金从小到大排序 2:单倍奖金从大到小)
     */
    public static List<BallSelectedBean> sortByAttribute(List<BallSelectedBean> list, Integer type)
    {
        Collections.sort(list, new Comparator()
        {
            @Override
            public int compare(Object o1, Object o2)
            {
                BallSelectedBean vo1 = (BallSelectedBean) o1;
                BallSelectedBean vo2 = (BallSelectedBean) o2;
                BigDecimal singlePrize1 = new BigDecimal(vo1.getSinglePrize());
                BigDecimal singlePrize2 = new BigDecimal(vo2.getSinglePrize());
                BigDecimal prize1 = new BigDecimal(vo1.getTotalPrize());
                BigDecimal prize2 = new BigDecimal(vo2.getTotalPrize());
                switch (type)
                {
                    case 0:
                        if (singlePrize1.compareTo(singlePrize2) == 1)
                        {
                            return 1;
                        }
                        else if (singlePrize1.compareTo(singlePrize2) == 0)
                        {
                            return 0;
                        }
                        else
                        {
                            return -1;
                        }
                    case 1:
                        if (prize1.compareTo(prize2) == 1)
                        {
                            return 1;
                        }
                        else if (prize1.compareTo(prize2) == 0)
                        {
                            return 0;
                        }
                        else
                        {
                            return -1;
                        }
                    case 2:
                        if (prize2.compareTo(prize1) == 1)
                        {
                            return 1;
                        }
                        else if (prize2.compareTo(prize1) == 0)
                        {
                            return 0;
                        }
                        else
                        {
                            return -1;
                        }
                    default:
                        return 0;

                }
            }
        });
        return list;
    }

    /**
     * @return Boolean
     * @Description 判断是否支持博冷和博热
     * @Author 郭靖
     * @Date 11:00 2018/12/28
     * @Param [list, payAmount] dl：投注列表、投注金额
     **/
    public static Boolean isSupportHotOrCold(List<BallSelectedBean> list, int payAmount)
    {
        if (list == null || list.size() < 1)
        {
            return false;
        }
        List<BigDecimal> l = new ArrayList<>();
        for (BallSelectedBean b : list)
        {
            l.add(new BigDecimal(b.getTotalPrize()));
        }
        BigDecimal minPrize = Collections.min(l);
        if (minPrize.compareTo(new BigDecimal(payAmount)) == -1)
        {
            return false;
        }
        return true;
    }
}
